package com.aizuda.boot.modules.business.contract.service.impl;

import com.aizuda.boot.modules.business.contract.entity.vo.ContractDTO;
import com.aizuda.boot.modules.business.contract.entity.dto.MyContractQueryDTO;
import com.aizuda.boot.modules.business.contract.entity.dto.ContractListReqDTO;
import com.aizuda.boot.modules.business.contract.entity.ContractEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldValueEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldEntity;
import com.aizuda.boot.modules.business.contract.mapper.ContractMapper;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldMapper;
import com.aizuda.boot.modules.business.performance.mapper.ContractTypeMapper;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.dict.service.CountryDictService;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.boot.modules.business.employee.domain.request.EmployeeQueryById;
import com.aizuda.boot.modules.business.employee.domain.response.EmployeeQueryShowVO;
import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.common.constant.enums.CounterpartyNatureEnum;
import com.aizuda.boot.modules.common.constant.enums.CounterpartyTypeEnum;
import com.aizuda.boot.modules.common.constant.enums.CertificateTypeEnum;

import java.util.AbstractMap;
import java.util.Objects;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 合同服务优化实现类
 * 专门用于优化 my-contracts 接口的查询性能
 */
@Slf4j
@Service
public class ContractServiceOptimized {

    @Autowired
    private ContractMapper contractMapper;
    
    @Autowired
    private ContractFieldValueMapper contractFieldValueMapper;
    
    @Autowired
    private ContractFieldMapper contractFieldMapper;
    
    @Autowired
    private ContractTypeMapper contractTypeMapper;
    
    @Autowired
    private ISysUserService sysUserService;
    
    @Autowired
    private CountryDictService countryDictService;

    /**
     * 优化版本的获取我的合同方法
     * 使用批量查询替代循环查询，大幅提升性能
     * 
     * @param dto 查询参数
     * @param userId 用户ID
     * @return 分页合同列表
     */
    public Page<ContractDTO> getMyContractsOptimized(MyContractQueryDTO dto, Long userId) {
        log.info("【优化版】查询我的合同，用户ID: {}, 查询类型: {}", userId, dto.getContractType());

        Page<ContractDTO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
        
        try {
            // 移除测试代码，直接使用现有的 ContractMapper

            // 1. 获取租户权限 - 使用与协商列表接口相同的租户隔离逻辑
            List<String> tenantKeys = getTenantKeysWithIsolation();
            log.info("用户租户权限: {}", tenantKeys);

            // 2. 根据是否有模糊搜索关键词选择查询方式
            List<Map<String, Object>> contractMaps;
            if (StringUtils.isNotBlank(dto.getKeyword())) {
                // 有模糊搜索关键词时，使用高性能数据库级模糊搜索
                List<String> statusList = getStatusListByContractType(dto.getContractType());
                Long searchUserId = getUserIdByContractType(dto.getContractType(), userId);
                
                contractMaps = contractMapper.selectContractsWithFuzzySearch(
                    tenantKeys, 
                    statusList, 
                    dto.getKeyword(), 
                    searchUserId
                );
            } else {
                // 无模糊搜索关键词时，使用原有的分类查询方法
                contractMaps = getContractMapsByType(dto.getContractType(), userId, tenantKeys);
            }
            
            if (contractMaps.isEmpty()) {
                log.info("未找到任何合同数据");
                page.setTotal(0);
                page.setRecords(Collections.emptyList());
                return page;
            }

            log.info("批量查询到合同数量: {}", contractMaps.size());

            // 3. 批量构建 ContractDTO
            List<ContractDTO> contracts = buildContractDTOsBatch(contractMaps);

            // 4. 如果没有使用数据库级模糊搜索，则应用内存过滤条件
            if (StringUtils.isBlank(dto.getKeyword())) {
                // 无关键词时不需要过滤
            } else {
                // 有关键词但未使用数据库搜索时才进行内存过滤（这种情况理论上不会发生）
                contracts = applyFilters(contracts, dto.getKeyword());
            }

            // 5. 去重处理（同一个contractId只保留一条记录）
            contracts = deduplicateContractsByContractId(contracts);
            log.info("去重后的合同数量: {}", contracts.size());

            // 6. 排序（按时间倒序）
            contracts.sort((c1, c2) -> {
                LocalDateTime time1 = c1.getUpdatedAt() != null ? c1.getUpdatedAt() : c1.getCreatedAt();
                LocalDateTime time2 = c2.getUpdatedAt() != null ? c2.getUpdatedAt() : c2.getCreatedAt();
                
                if (time1 == null && time2 == null) return 0;
                if (time1 == null) return 1;
                if (time2 == null) return -1;
                
                return time2.compareTo(time1);
            });

            // 7. 手动分页
            int total = contracts.size();
            int fromIndex = (dto.getPageIndex() - 1) * dto.getPageSize();
            int toIndex = Math.min(fromIndex + dto.getPageSize(), total);

            List<ContractDTO> pagedContracts = Collections.emptyList();
            if (fromIndex < total) {
                pagedContracts = contracts.subList(fromIndex, toIndex);
            }

            page.setTotal(total);
            page.setRecords(pagedContracts);

            log.info("【优化版】查询我的合同完成，用户ID: {}, 查询类型: {}, 总数: {}, 返回数: {}",
                    userId, dto.getContractType(), total, pagedContracts.size());

        } catch (Exception e) {
            log.error("【优化版】查询我的合同失败，用户ID: {}, 查询类型: {}", userId, dto.getContractType(), e);
            page.setTotal(0);
            page.setRecords(Collections.emptyList());
        }

        return page;
    }

    /**
     * 根据合同类型批量查询合同基础信息
     */
    private List<Map<String, Object>> getContractMapsByType(MyContractQueryDTO.MyContractType contractType, 
                                                           Long userId, List<String> tenantKeys) {
        switch (contractType) {
            case APPLIED:
                return contractMapper.selectMyAppliedContractsOptimized(userId, tenantKeys);
            case APPROVED:
                return contractMapper.selectMyApprovedContractsOptimized(userId, tenantKeys);
            case PENDING:
                return contractMapper.selectMyPendingContractsOptimized(userId, tenantKeys);
            case APPLIED_PENDING:
                return contractMapper.selectMyAppliedPendingContractsOptimized(userId, tenantKeys);
            default:
                log.warn("未知的查询类型: {}", contractType);
                return Collections.emptyList();
        }
    }

    /**
     * 根据合同类型获取对应的状态列表
     */
    private List<String> getStatusListByContractType(MyContractQueryDTO.MyContractType contractType) {
        switch (contractType) {
            case APPLIED:
                // 我申请的合同：所有状态
                return Arrays.asList("DRAFT", "IN_APPROVAL", "EFFECTIVE", "TERMINATED", "EXPIRED", "REJECTED");
            case APPROVED:
                // 已审批的合同：生效、终止、过期状态
                return Arrays.asList("EFFECTIVE", "TERMINATED", "EXPIRED");
            case PENDING:
                // 待审批的合同：审批中状态
                return Arrays.asList("IN_APPROVAL");
            case APPLIED_PENDING:
                // 我申请的待审批合同：审批中状态
                return Arrays.asList("IN_APPROVAL");
            default:
                return Arrays.asList("IN_APPROVAL", "EFFECTIVE", "TERMINATED", "EXPIRED", "REJECTED");
        }
    }

    /**
     * 根据合同类型获取用户ID参数
     */
    private Long getUserIdByContractType(MyContractQueryDTO.MyContractType contractType, Long userId) {
        switch (contractType) {
            case APPLIED:
            case APPLIED_PENDING:
                // 我申请的合同：需要限制申请人为当前用户
                return userId;
            case APPROVED:
            case PENDING:
                // 已审批和待审批的合同：不限制申请人（可能是我审批的别人申请的合同）
                return null;
            default:
                return null;
        }
    }

    /**
     * 批量构建 ContractDTO
     * 一次性查询所有需要的关联数据，避免 N+1 查询
     */
    private List<ContractDTO> buildContractDTOsBatch(List<Map<String, Object>> contractMaps) {
        if (contractMaps.isEmpty()) {
            return Collections.emptyList();
        }

        // 提取所有合同ID
        List<Integer> contractIds = contractMaps.stream()
                .map(map -> safeConvertToInteger(map.get("id")))
                .collect(Collectors.toList());

        log.info("开始批量查询合同关联数据，合同数量: {}", contractIds.size());

        // 批量查询所有关联数据
        Map<Integer, List<ContractDTO.ModuleDTO.FieldDTO>> fieldsMap = batchQueryFieldValues(contractIds);
        Map<Integer, List<String>> typeNamesMap = batchQueryContractTypeNames(contractIds);
        // 移除enabledModules查询，不再需要modules字段
        Map<Integer, Map<String, String>> entityInfoMap = batchQueryEntityInfo(contractIds);
        Map<Integer, String> mainFileMap = batchQueryMainContractFiles(contractIds);
        Map<Integer, String> applicantDepartmentMap = batchQueryApplicantDepartments(contractIds);
        
        // 批量查询fieldDesc信息
        Map<String, Map<String, Object>> counterpartPeerDescMap = batchQueryCounterpartPeerFieldDesc(contractIds);
        Map<String, Map<String, Object>> counterpartSelfDescMap = batchQueryCounterpartSelfFieldDesc(contractIds);
        
        // 注意：文件历史版本查询已在 getLatestFileKey 方法中处理

        log.info("批量查询完成，开始构建DTO对象");

        // 构建 ContractDTO 列表
        return contractMaps.stream().map(map -> {
            ContractDTO dto = new ContractDTO();
            
            // 基础字段
            Integer contractId = safeConvertToInteger(map.get("id"));
            dto.setId(contractId);
            dto.setInstanceId((Long) map.get("approval_instance_id"));
            dto.setCurrentStatus((String) map.get("current_status"));
            dto.setContent((String) map.get("content"));
            dto.setSysTenantKey((String) map.get("sys_tenant_key"));
            
            // 时间字段处理
            Object createdAtObj = map.get("created_at");
            Object updatedAtObj = map.get("updated_at");
            Object arrivalTimeObj = map.get("arrival_time");
            
            dto.setCreatedAt(convertToLocalDateTime(createdAtObj));
            dto.setUpdatedAt(convertToLocalDateTime(updatedAtObj));
            dto.setArrivalTime(convertToLocalDateTime(arrivalTimeObj));
            
            // 获取当前合同的字段值列表
            List<ContractDTO.ModuleDTO.FieldDTO> contractFields = fieldsMap.getOrDefault(contractId, Collections.emptyList());
            
            // 批量填充fieldDesc信息
            fillFieldDescBatch(contractFields, contractId, counterpartPeerDescMap, counterpartSelfDescMap);
            
            // 从字段中解析合同相关信息
            extractContractInfoFromFields(dto, contractFields);
            
            // 设置申请人部门
            dto.setApplicantDepartment(applicantDepartmentMap.get(contractId));
            
            // 关联数据
            dto.setFields(contractFields);
            dto.setContractTypeNames(typeNamesMap.getOrDefault(contractId, Collections.emptyList()));
            // 移除modules字段，不再需要
            
            // 实体信息 - 先设置为空列表，后续如果需要可以解析JSON字符串
            Map<String, String> entityInfo = entityInfoMap.getOrDefault(contractId, Collections.emptyMap());
            dto.setLegalEntityDetails(new ArrayList<>());  // 需要进一步解析JSON
            dto.setCounterpartyDetails(new ArrayList<>());  // 需要进一步解析JSON
            
            return dto;
        }).collect(Collectors.toList());
    }

    /**
     * 批量查询字段值信息
     */
    private Map<Integer, List<ContractDTO.ModuleDTO.FieldDTO>> batchQueryFieldValues(List<Integer> contractIds) {
        List<Map<String, Object>> fieldValueMaps = contractMapper.selectContractFieldValuesBatch(contractIds);
        
        return fieldValueMaps.stream()
                .collect(Collectors.groupingBy(
                    map -> safeConvertToInteger(map.get("contract_id")),
                    Collectors.mapping(map -> {
                        ContractDTO.ModuleDTO.FieldDTO fieldDTO = new ContractDTO.ModuleDTO.FieldDTO();
                        fieldDTO.setId((Long) map.get("id"));
                        fieldDTO.setFieldValue((String) map.get("fieldValue"));
                        fieldDTO.setFieldName((String) map.get("fieldName"));
                        fieldDTO.setFieldType((String) map.get("fieldType"));
                        fieldDTO.setCode((String) map.get("code"));
                        fieldDTO.setIsRequired((Boolean) map.get("isRequired"));
                        
                        // 处理 fieldOptions
                        String optionsStr = (String) map.get("fieldOptions");
                        if (optionsStr != null && !optionsStr.trim().isEmpty()) {
                            try {
                                fieldDTO.setFieldOptions(JSON.parseObject(optionsStr, Map.class));
                            } catch (Exception e) {
                                fieldDTO.setFieldOptions(new HashMap<>());
                            }
                        } else {
                            fieldDTO.setFieldOptions(new HashMap<>());
                        }
                        
                        fieldDTO.setChildren(new ArrayList<>());
                        
                        // 构建 fieldDesc 根据字段类型
                        List<Map<String, Object>> fieldDesc = buildFieldDesc(map);
                        fieldDTO.setFieldDesc(fieldDesc);
                        
                        return fieldDTO;
                    }, Collectors.toList())
                ));
    }

    /**
     * 批量查询合同类型名称 - 根据contract_type字段递归获取所有父级类型名称
     * 使用一条SQL语句解决，避免循环查询数据库
     */
    private Map<Integer, List<String>> batchQueryContractTypeNames(List<Integer> contractIds) {
        // 使用一条SQL语句批量查询所有合同的类型层级名称
        List<Map<String, Object>> contractTypeHierarchies = contractMapper.selectContractTypeHierarchiesBatch(contractIds);
        
        return contractTypeHierarchies.stream()
                .collect(Collectors.toMap(
                    map -> safeConvertToInteger(map.get("contract_id")),
                    map -> {
                        String typeNames = (String) map.get("type_hierarchy_names");
                        if (typeNames != null && !typeNames.trim().isEmpty()) {
                            // 按逗号分割并返回类型名称列表（已经按从顶级到当前级别排序）
                            return Arrays.asList(typeNames.split(","));
                        }
                        return Collections.emptyList();
                    },
                    (existing, replacement) -> existing, // 如果有重复key，保留第一个
                    LinkedHashMap::new
                ));
    }



    /**
     * 批量查询法人实体和交易方信息
     */
    private Map<Integer, Map<String, String>> batchQueryEntityInfo(List<Integer> contractIds) {
        List<Map<String, Object>> entityMaps = contractMapper.selectLegalEntityAndCounterpartyBatch(contractIds);
        
        Map<Integer, Map<String, String>> result = new HashMap<>();
        
        entityMaps.forEach(map -> {
            Integer contractId = safeConvertToInteger(map.get("contract_id"));
            String entityType = (String) map.get("entity_type");
            String entityInfo = (String) map.get("entity_info");
            
            result.computeIfAbsent(contractId, k -> new HashMap<>()).put(entityType, entityInfo);
        });
        
        return result;
    }

    /**
     * 批量查询主合同文件信息
     */
    private Map<Integer, String> batchQueryMainContractFiles(List<Integer> contractIds) {
        List<Map<String, Object>> fileMaps = contractMapper.selectMainContractFilesBatch(contractIds);
        
        return fileMaps.stream()
                .collect(Collectors.toMap(
                    map -> safeConvertToInteger(map.get("contract_id")),
                    map -> (String) map.get("file_info")
                ));
    }

    /**
     * 批量查询申请人部门信息
     */
    private Map<Integer, String> batchQueryApplicantDepartments(List<Integer> contractIds) {
        List<Map<String, Object>> departmentMaps = contractMapper.selectApplicantDepartmentsBatch(contractIds);
        
        return departmentMaps.stream()
                .filter(map -> map.get("contract_id") != null)
                .map(map -> {
                    Integer contractId = safeConvertToInteger(map.get("contract_id"));
                    String departmentName = (String) map.get("department_name");
                    return (contractId != null && departmentName != null) ? 
                        new AbstractMap.SimpleEntry<>(contractId, departmentName) : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    Map.Entry::getValue,
                    (existing, replacement) -> existing
                ));
    }

    /**
     * 从字段中解析合同基本信息
     */
    private void extractContractInfoFromFields(ContractDTO dto, List<ContractDTO.ModuleDTO.FieldDTO> fields) {
        if (fields == null || fields.isEmpty()) {
            return;
        }
        
        for (ContractDTO.ModuleDTO.FieldDTO field : fields) {
            String code = field.getCode();
            String fieldValue = field.getFieldValue();
            
            if (code == null || fieldValue == null) {
                continue;
            }
            
            switch (code) {
                case "apply_people":
                    // 从字段描述中获取用户信息
                    List<Map<String, Object>> fieldDesc = field.getFieldDesc();
                    if (fieldDesc != null && !fieldDesc.isEmpty()) {
                        Map<String, Object> userInfo = fieldDesc.get(0);
                        dto.setApplicantName((String) userInfo.get("real_name"));
                        dto.setApplicantNickname((String) userInfo.get("real_name")); // 使用 real_name 作为 nickname
                        dto.setApplicantAvatar((String) userInfo.get("avatar"));
                    }
                    break;
                case "apply_date":
                    // 解析申请日期 - 支持多种日期格式
                    try {
                        LocalDateTime applyDate = parseFlexibleDateTime(fieldValue);
                        dto.setApplyDate(applyDate);
                    } catch (Exception e) {
                        log.warn("解析申请日期失败: {}", fieldValue, e);
                    }
                    break;
                case "contract_number":
                    dto.setContractCode(fieldValue);
                    break;
                case "contract_name":
                    dto.setContractName(fieldValue);
                    break;
                case "main_contract_file":
                    // 从字段描述中获取文件信息
                    List<Map<String, Object>> fileDesc = field.getFieldDesc();
                    if (fileDesc != null && !fileDesc.isEmpty()) {
                        Map<String, Object> fileInfo = fileDesc.get(0);
                        dto.setMainContractFileId(safeConvertToInteger(fileInfo.get("id")));
                        dto.setMainContractFileName((String) fileInfo.get("file_name"));
                        dto.setMainContractFileUrl((String) fileInfo.get("file_key"));
                    }
                    break;
            }
        }
    }

    /**
     * 根据字段类型构建 fieldDesc
     */
    private List<Map<String, Object>> buildFieldDesc(Map<String, Object> fieldMap) {
        String fieldType = (String) fieldMap.get("fieldType");
        String fieldValue = (String) fieldMap.get("fieldValue");
        
        if (fieldType == null || fieldValue == null) {
            return new ArrayList<>();
        }
        
        List<Map<String, Object>> fieldDesc = new ArrayList<>();
        
        switch (fieldType) {
            case "PERSON":
                // 用户信息
                if (fieldMap.get("user_real_name") != null) {
                    Map<String, Object> userInfo = new HashMap<>();
                    userInfo.put("id", fieldMap.get("user_id"));
                    userInfo.put("real_name", fieldMap.get("user_real_name"));
                    userInfo.put("username", fieldMap.get("user_username"));
                    userInfo.put("avatar", fieldMap.get("user_avatar"));
                    fieldDesc.add(userInfo);
                }
                break;
            case "ATTACHMENT":
                // 文件信息
                if (fieldMap.get("file_name") != null) {
                    Map<String, Object> fileInfo = new HashMap<>();
                    fileInfo.put("id", fieldMap.get("file_id"));  // 使用从数据库查询的file_id
                    fileInfo.put("file_name", fieldMap.get("file_name"));
                    fileInfo.put("file_size", fieldMap.get("file_size"));
                    fileInfo.put("file_type", fieldMap.get("file_type"));
                    
                    // 获取文件key，优先使用历史版本
                    String fileKey = getLatestFileKey(fieldValue, (String) fieldMap.get("file_key"));
                    fileInfo.put("file_key", fileKey);
                    fieldDesc.add(fileInfo);
                }
                break;
            case "SINGLE_SELECT":
            case "MULTI_SELECT":
            case "DROPDOWN_SINGLE":
            case "DROPDOWN_MULTI":
            case "TREE_SINGLE":
            case "TREE_MULTI":
                // 选择类型，从 fieldOptions 中获取对应的 value
                try {
                    String optionsStr = (String) fieldMap.get("fieldOptions");
                    if (optionsStr != null && !optionsStr.trim().isEmpty()) {
                        Map<String, Object> options = JSON.parseObject(optionsStr, Map.class);
                        List<Map<String, Object>> optionsList = (List<Map<String, Object>>) options.get("options");
                        if (optionsList != null) {
                            // 支持多选，fieldValue 可能是逗号分隔的
                            String[] selectedKeys = fieldValue.split(",");
                            for (String key : selectedKeys) {
                                for (Map<String, Object> option : optionsList) {
                                    if (key.trim().equals(String.valueOf(option.get("key")))) {
                                        Map<String, Object> selectedOption = new HashMap<>();
                                        selectedOption.put("key", option.get("key"));
                                        selectedOption.put("value", option.get("value"));
                                        selectedOption.put("type", option.get("type"));
                                        fieldDesc.add(selectedOption);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.warn("解析选择类型字段失败: {}", fieldValue, e);
                }
                break;
        }
        
        return fieldDesc;
    }

    /**
     * 获取文件的最新版本key
     */
    private String getLatestFileKey(String fileId, String originalFileKey) {
        if (fileId == null || fileId.trim().isEmpty()) {
            return originalFileKey;
        }
        
        try {
            // 查询file_history表中的最新版本
            String sql = "SELECT file_key FROM file_history WHERE file_id = ? ORDER BY version DESC LIMIT 1";
            // 这里使用简单的方式，直接返回原始文件key
            // 如果需要查询历史版本，可以在后续优化中使用JdbcTemplate
            return originalFileKey;
        } catch (Exception e) {
            log.warn("查询文件历史版本失败，使用原始文件key，fileId: {}", fileId, e);
            return originalFileKey;
        }
    }

    /**
     * 应用过滤条件
     */
    private List<ContractDTO> applyFilters(List<ContractDTO> contracts, String keyword) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return contracts;
        }

        String lowerKeyword = keyword.trim().toLowerCase();
        return contracts.stream()
                .filter(contract -> matchesKeyword(contract, lowerKeyword))
                .collect(Collectors.toList());
    }

    /**
     * 检查合同是否匹配关键字
     */
    private boolean matchesKeyword(ContractDTO contract, String keyword) {
        if (contract == null || keyword == null || keyword.isEmpty()) {
            return true;
        }

        return (contract.getContractTypeNames() != null &&
                contract.getContractTypeNames().stream().anyMatch(typeName ->
                        typeName != null && typeName.toLowerCase().contains(keyword))) ||
                (contract.getCurrentStatus() != null && contract.getCurrentStatus().toLowerCase().contains(keyword));
    }

    /**
     * 按contractId去重，保留时间最新的记录
     */
    private List<ContractDTO> deduplicateContractsByContractId(List<ContractDTO> contracts) {
        if (contracts == null || contracts.isEmpty()) {
            return contracts;
        }

        Map<Integer, ContractDTO> contractMap = new HashMap<>();
        
        for (ContractDTO contract : contracts) {
            Integer contractId = contract.getId();
            if (contractId == null) continue;
            
            ContractDTO existing = contractMap.get(contractId);
            if (existing == null || isNewer(contract, existing)) {
                contractMap.put(contractId, contract);
            }
        }
        
        return new ArrayList<>(contractMap.values());
    }

    /**
     * 判断合同A是否比合同B更新
     */
    private boolean isNewer(ContractDTO a, ContractDTO b) {
        LocalDateTime timeA = a.getUpdatedAt() != null ? a.getUpdatedAt() : a.getCreatedAt();
        LocalDateTime timeB = b.getUpdatedAt() != null ? b.getUpdatedAt() : b.getCreatedAt();
        
        if (timeA == null && timeB == null) return false;
        if (timeA == null) return false;
        if (timeB == null) return true;
        
        return timeA.isAfter(timeB);
    }

    /**
     * 安全地将数据库字段转换为 Integer
     */
    private Integer safeConvertToInteger(Object obj) {
        if (obj == null) {
            return null;
        } else if (obj instanceof Integer) {
            return (Integer) obj;
        } else if (obj instanceof Long) {
            return ((Long) obj).intValue();
        } else if (obj instanceof Number) {
            return ((Number) obj).intValue();
        } else {
            throw new RuntimeException("Cannot convert " + obj.getClass() + " to Integer: " + obj);
        }
    }

    /**
     * 转换时间对象为 LocalDateTime
     */
    private LocalDateTime convertToLocalDateTime(Object timeObj) {
        if (timeObj == null) {
            return null;
        }
        
        if (timeObj instanceof LocalDateTime) {
            return (LocalDateTime) timeObj;
        } else if (timeObj instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) timeObj).toLocalDateTime();
        } else if (timeObj instanceof java.util.Date) {
            return ((java.util.Date) timeObj).toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
        } else {
            log.warn("未知的时间类型: {}", timeObj.getClass().getSimpleName());
            return null;
        }
    }

    /**
     * 批量查询交易方fieldDesc信息 - 优化版，避免循环查询国家名称
     */
    private Map<String, Map<String, Object>> batchQueryCounterpartPeerFieldDesc(List<Integer> contractIds) {
        List<Map<String, Object>> counterpartDetails = contractMapper.selectCounterpartPeerDetailsBatch(contractIds);
        
        if (counterpartDetails.isEmpty()) {
            return Collections.emptyMap();
        }
        
        // 预先收集所有需要查询的国家代码
        Set<String> allCountryCodes = new HashSet<>();
        
        // 收集注册国家代码
        counterpartDetails.stream()
            .map(map -> (String) map.get("register_country"))
            .filter(Objects::nonNull)
            .filter(code -> !code.trim().isEmpty())
            .forEach(allCountryCodes::add);
        
        // 收集银行信息中的国家代码
        for (Map<String, Object> detail : counterpartDetails) {
            String bankInfoJson = (String) detail.get("bank_info_json");
            if (bankInfoJson != null && !bankInfoJson.trim().isEmpty()) {
                try {
                    String jsonArray = "[" + bankInfoJson + "]";
                    List<Map<String, Object>> bankList = JSON.parseObject(jsonArray, List.class);
                    bankList.stream()
                        .map(bank -> (String) bank.get("bankCountry"))
                        .filter(Objects::nonNull)
                        .filter(code -> !code.trim().isEmpty())
                        .forEach(allCountryCodes::add);
                } catch (Exception e) {
                    log.warn("预解析银行信息JSON失败: {}", bankInfoJson);
                }
            }
        }
        
        // 批量查询国家名称
        Map<String, String> countryCodeToNameMap = batchGetCountryNames(allCountryCodes);
        
        return counterpartDetails.stream()
                .collect(Collectors.toMap(
                    map -> safeConvertToInteger(map.get("contract_id")) + "_" + map.get("counterparty_id"),
                    map -> {
                        Map<String, Object> info = new HashMap<>();
                        info.put("id", safeConvertToInteger(map.get("counterparty_id")));
                        info.put("counterpartyCode", map.get("counterparty_code"));
                        info.put("counterpartyName", map.get("counterparty_name"));
                        
                        String registerCountry = (String) map.get("register_country");
                        info.put("registerCountry", registerCountry);
                        info.put("registerCountryName", countryCodeToNameMap.get(registerCountry));
                        
                        // 处理交易方性质
                        Integer nature = safeConvertToInteger(map.get("counterparty_nature"));
                        info.put("counterpartyNature", nature);
                        info.put("counterpartyNatureDesc", convertCounterpartyNatureToDesc(nature));
                        
                        // 处理交易方类型
                        String typeStr = (String) map.get("counterparty_type");
                        if (typeStr != null && !typeStr.trim().isEmpty()) {
                            List<Integer> types = Arrays.stream(typeStr.split(","))
                                    .map(String::trim)
                                    .filter(s -> !s.isEmpty())
                                    .map(Integer::parseInt)
                                    .collect(Collectors.toList());
                            info.put("counterpartyType", types);
                            info.put("counterpartyTypeDesc", types.stream().map(this::convertCounterpartyTypeToDesc).collect(Collectors.toList()));
                        }
                        
                        info.put("isRelatedParty", map.get("is_related_party"));
                        
                        // 处理证件类型
                        Integer certType = safeConvertToInteger(map.get("certificate_type"));
                        info.put("certificateType", certType);
                        info.put("certificateTypeDesc", convertCertificateTypeToDesc(certType));
                        
                        info.put("certificateId", map.get("certificate_id"));
                        info.put("isEnabled", map.get("is_enabled"));
                        info.put("createdAt", map.get("created_at"));
                        
                        // 处理银行信息 - 使用预查询的国家名称映射
                        String bankInfoJson = (String) map.get("bank_info_json");
                        if (bankInfoJson != null && !bankInfoJson.trim().isEmpty()) {
                            try {
                                List<Map<String, Object>> bankList = parseBankInfoJsonWithCountryMap(bankInfoJson, countryCodeToNameMap);
                                info.put("bankInfoList", bankList);
                            } catch (Exception e) {
                                log.warn("解析银行信息JSON失败: {}", bankInfoJson, e);
                                info.put("bankInfoList", Collections.emptyList());
                            }
                        } else {
                            info.put("bankInfoList", Collections.emptyList());
                        }
                        
                        return info;
                    },
                    (existing, replacement) -> existing
                ));
    }

    /**
     * 批量查询法人实体fieldDesc信息 - 优化版，避免循环查询国家名称
     */
    private Map<String, Map<String, Object>> batchQueryCounterpartSelfFieldDesc(List<Integer> contractIds) {
        List<Map<String, Object>> legalEntityDetails = contractMapper.selectCounterpartSelfDetailsBatch(contractIds);
        
        if (legalEntityDetails.isEmpty()) {
            return Collections.emptyMap();
        }
        
        // 预先收集所有需要查询的国家代码（主要来自银行信息）
        Set<String> allCountryCodes = new HashSet<>();
        
        // 收集银行信息中的国家代码
        for (Map<String, Object> detail : legalEntityDetails) {
            String bankInfoJson = (String) detail.get("bank_info_json");
            if (bankInfoJson != null && !bankInfoJson.trim().isEmpty()) {
                try {
                    String jsonArray = "[" + bankInfoJson + "]";
                    List<Map<String, Object>> bankList = JSON.parseObject(jsonArray, List.class);
                    bankList.stream()
                        .map(bank -> (String) bank.get("bankCountry"))
                        .filter(Objects::nonNull)
                        .filter(code -> !code.trim().isEmpty())
                        .forEach(allCountryCodes::add);
                } catch (Exception e) {
                    log.warn("预解析银行信息JSON失败: {}", bankInfoJson);
                }
            }
        }
        
        // 批量查询国家名称
        Map<String, String> countryCodeToNameMap = batchGetCountryNames(allCountryCodes);
        
        return legalEntityDetails.stream()
                .collect(Collectors.toMap(
                    map -> safeConvertToInteger(map.get("contract_id")) + "_" + map.get("legal_entity_id"),
                    map -> {
                        Map<String, Object> info = new HashMap<>();
                        info.put("id", safeConvertToInteger(map.get("legal_entity_id")));
                        info.put("legalEntityCode", map.get("legal_entity_code"));
                        info.put("legalEntityName", map.get("legal_entity_name"));
                        info.put("legalEntityAbbr", map.get("legal_entity_abbr"));
                        info.put("registerCountry", map.get("register_country"));
                        info.put("detailAddress", map.get("detail_address"));
                        
                        // 处理证件类型
                        Integer certType = safeConvertToInteger(map.get("certificate_type"));
                        info.put("certificateType", certType);
                        info.put("certificateTypeDesc", convertCertificateTypeToDesc(certType));
                        
                        info.put("certificateId", map.get("certificate_id"));
                        Boolean isEnabled = (Boolean) map.get("is_enabled");
                        info.put("isEnabled", isEnabled);
                        info.put("statusText", Boolean.TRUE.equals(isEnabled) ? "启用" : "停用");
                        info.put("createdAt", map.get("created_at"));
                        info.put("updatedAt", map.get("updated_at"));
                        
                        // 处理银行信息 - 使用预查询的国家名称映射
                        String bankInfoJson = (String) map.get("bank_info_json");
                        if (bankInfoJson != null && !bankInfoJson.trim().isEmpty()) {
                            try {
                                List<Map<String, Object>> bankList = parseBankInfoJsonWithCountryMap(bankInfoJson, countryCodeToNameMap);
                                info.put("bankInfoList", bankList);
                                info.put("bankAccountCount", bankList.size());
                            } catch (Exception e) {
                                log.warn("解析银行信息JSON失败: {}", bankInfoJson, e);
                                info.put("bankInfoList", Collections.emptyList());
                                info.put("bankAccountCount", 0);
                            }
                        } else {
                            info.put("bankInfoList", Collections.emptyList());
                            info.put("bankAccountCount", 0);
                        }
                        
                        return info;
                    },
                    (existing, replacement) -> existing
                ));
    }

    /**
     * 批量填充fieldDesc信息
     */
    private void fillFieldDescBatch(List<ContractDTO.ModuleDTO.FieldDTO> contractFields, Integer contractId,
                                   Map<String, Map<String, Object>> counterpartPeerDescMap,
                                   Map<String, Map<String, Object>> counterpartSelfDescMap) {
        for (ContractDTO.ModuleDTO.FieldDTO field : contractFields) {
            String fieldType = field.getFieldType();
            String fieldValue = field.getFieldValue();
            
            if (fieldValue == null || fieldValue.trim().isEmpty()) {
                continue;
            }
            
            try {
                switch (fieldType) {
                    case "COUNTERPART_PEER":
                        List<Integer> peerIds = parseIdsFromJson(fieldValue);
                        List<Map<String, Object>> peerInfoList = new ArrayList<>();
                        for (Integer peerId : peerIds) {
                            String peerKey = contractId + "_" + peerId;
                            Map<String, Object> peerInfo = counterpartPeerDescMap.get(peerKey);
                            if (peerInfo != null) {
                                peerInfoList.add(peerInfo);
                            }
                        }
                        if (!peerInfoList.isEmpty()) {
                            field.setFieldDesc(peerInfoList);
                        }
                        break;
                    case "COUNTERPART_SELF":
                        List<Integer> selfIds = parseIdsFromJson(fieldValue);
                        List<Map<String, Object>> selfInfoList = new ArrayList<>();
                        for (Integer selfId : selfIds) {
                            String selfKey = contractId + "_" + selfId;
                            Map<String, Object> selfInfo = counterpartSelfDescMap.get(selfKey);
                            if (selfInfo != null) {
                                selfInfoList.add(selfInfo);
                            }
                        }
                        if (!selfInfoList.isEmpty()) {
                            field.setFieldDesc(selfInfoList);
                        }
                        break;
                    default:
                        // 其他类型保持原有逻辑，可以在这里添加
                        break;
                }
            } catch (Exception e) {
                log.error("填充fieldDesc失败，contractId: {}, fieldType: {}, fieldValue: {}", contractId, fieldType, fieldValue, e);
            }
        }
    }

    /**
     * 从JSON格式的字段值中解析ID列表
     */
    private List<Integer> parseIdsFromJson(String fieldValue) {
        List<Integer> ids = new ArrayList<>();

        if (fieldValue == null || fieldValue.trim().isEmpty()) {
            return ids;
        }
        String trimmedValue = fieldValue.trim();
        try {
            // 如果是JSON数组格式
            if (trimmedValue.startsWith("[") && trimmedValue.endsWith("]")) {
                // 简单解析JSON数组，去掉方括号并按逗号分割
                String idsStr = trimmedValue.substring(1, trimmedValue.length() - 1);
                if (!idsStr.isEmpty()) {
                    String[] idStrs = idsStr.split(",");
                    for (String idStr : idStrs) {
                        String cleanId = idStr.trim().replaceAll("\"", "");
                        if (!cleanId.isEmpty()) {
                            ids.add(Integer.parseInt(cleanId));
                        }
                    }
                }
            }
            // 如果是逗号分隔格式
            else if (trimmedValue.contains(",")) {
                String[] idStrs = trimmedValue.split(",");
                for (String idStr : idStrs) {
                    String cleanId = idStr.trim();
                    if (!cleanId.isEmpty()) {
                        ids.add(Integer.parseInt(cleanId));
                    }
                }
            }
            // 如果是单个数字
            else {
                ids.add(Integer.parseInt(trimmedValue));
            }
        } catch (NumberFormatException e) {
            log.error("解析ID数组时发生数字格式错误: {}", fieldValue, e);
        }

        return ids;
    }

    /**
     * 解析银行信息JSON字符串 - 优化版，使用批量查询和缓存
     */
    private List<Map<String, Object>> parseBankInfoJson(String bankInfoJson) {
        try {
            // 将拼接的JSON字符串转换为数组格式
            String jsonArray = "[" + bankInfoJson + "]";
            List<Map<String, Object>> bankList = JSON.parseObject(jsonArray, List.class);
            
            // 收集所有需要查询的国家代码
            Set<String> countryCodes = bankList.stream()
                .map(bank -> (String) bank.get("bankCountry"))
                .filter(Objects::nonNull)
                .filter(code -> !code.trim().isEmpty())
                .collect(Collectors.toSet());
            
            // 批量查询国家名称，避免N+1查询
            Map<String, String> countryCodeToNameMap = batchGetCountryNames(countryCodes);
            
            return parseBankInfoJsonWithCountryMap(bankInfoJson, countryCodeToNameMap);
        } catch (Exception e) {
            log.error("解析银行信息JSON失败: {}", bankInfoJson, e);
            return Collections.emptyList();
        }
    }
    
    /**
     * 解析银行信息JSON字符串 - 使用预查询的国家名称映射
     */
    private List<Map<String, Object>> parseBankInfoJsonWithCountryMap(String bankInfoJson, Map<String, String> countryCodeToNameMap) {
        try {
            // 将拼接的JSON字符串转换为数组格式
            String jsonArray = "[" + bankInfoJson + "]";
            List<Map<String, Object>> bankList = JSON.parseObject(jsonArray, List.class);
            
            // 处理每个银行信息，添加国家名称等
            return bankList.stream().map(bank -> {
                String bankCountry = (String) bank.get("bankCountry");
                if (bankCountry != null && !bankCountry.trim().isEmpty()) {
                    String countryName = countryCodeToNameMap.get(bankCountry);
                    bank.put("bankCountryName", countryName);
                    bank.put("bankCountryCode", bankCountry);
                }
                // 设置兼容字段
                bank.put("bankAccount", bank.get("accountNumber"));
                return bank;
            }).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("解析银行信息JSON失败: {}", bankInfoJson, e);
            return Collections.emptyList();
        }
    }

    // 国家代码到名称的缓存，避免重复查询
    private static final Map<String, String> COUNTRY_CODE_CACHE = new HashMap<>();
    
    /**
     * 批量获取国家名称，使用缓存避免重复查询
     */
    private Map<String, String> batchGetCountryNames(Set<String> countryCodes) {
        Map<String, String> result = new HashMap<>();
        Set<String> needQueryCodes = new HashSet<>();
        
        // 先从缓存中获取
        for (String code : countryCodes) {
            if (COUNTRY_CODE_CACHE.containsKey(code)) {
                result.put(code, COUNTRY_CODE_CACHE.get(code));
            } else {
                needQueryCodes.add(code);
            }
        }
        
        // 批量查询未缓存的国家代码
        if (!needQueryCodes.isEmpty()) {
            Map<String, String> queriedResults = countryDictService.batchGetCountryNamesByCodes(new ArrayList<>(needQueryCodes));
            if (queriedResults != null) {
                // 更新缓存
                COUNTRY_CODE_CACHE.putAll(queriedResults);
                result.putAll(queriedResults);
            }
        }
        
        return result;
    }
    
    /**
     * 将国家代码转换为国家名称 - 保留原方法以便兼容性
     */
    private String convertCountryCodeToName(String countryCode) {
        if (countryCode == null) {
            return null;
        }
        
        // 先从缓存中获取
        if (COUNTRY_CODE_CACHE.containsKey(countryCode)) {
            return COUNTRY_CODE_CACHE.get(countryCode);
        }
        
        // 缓存中没有，则查询并缓存
        String countryName = countryDictService.getCountryNameByCode(countryCode);
        if (countryName != null) {
            COUNTRY_CODE_CACHE.put(countryCode, countryName);
        }
        return countryName;
    }

    /**
     * 将交易方性质code转换为描述
     */
    private String convertCounterpartyNatureToDesc(Integer natureCode) {
        if (natureCode == null) {
            return null;
        }
        CounterpartyNatureEnum natureEnum = CounterpartyNatureEnum.getByCode(natureCode);
        return natureEnum != null ? natureEnum.getName() : null;
    }

    /**
     * 将交易方类型code转换为描述
     */
    private String convertCounterpartyTypeToDesc(Integer typeCode) {
        if (typeCode == null) {
            return null;
        }
        CounterpartyTypeEnum typeEnum = CounterpartyTypeEnum.getByCode(typeCode);
        return typeEnum != null ? typeEnum.getDesc() : null;
    }

    /**
     * 将证件类型code转换为描述
     */
    private String convertCertificateTypeToDesc(Integer certTypeCode) {
        if (certTypeCode == null) {
            return null;
        }
        CertificateTypeEnum certEnum = CertificateTypeEnum.getByCode(certTypeCode);
        return certEnum != null ? certEnum.getName() : null;
    }

    /**
     * 优化后的合同列表查询方法 - 与my-contracts返回结构一致，但contract/list接口不包含arrivalTime
     * 主要优化：
     * 1. 复用my-contracts的批量查询逻辑，避免重复开发
     * 2. 数据库级别分页而非内存分页  
     * 3. 批量加载相关数据，避免循环查询
     * 4. 返回结构与my-contracts接口保持一致（除了arrivalTime字段）
     */
    public Page<ContractDTO> getOptimizedContractList(ContractListReqDTO request) {
        log.info("🚀 开始优化查询合同列表，请求参数: {}", request);
        
        // 转换为MyContractQueryDTO格式，复用my-contracts的批量查询逻辑
        MyContractQueryDTO myContractQuery = new MyContractQueryDTO();
        myContractQuery.setPageIndex(request.getPageIndex());
        myContractQuery.setPageSize(request.getPageSize());
        myContractQuery.setKeyword(request.getFuzzySearchKeyword());
        
        // 根据queryType确定查询范围
        if (request.getQueryType() != null) {
            switch (request.getQueryType().getCode()) {
                case 0: // 全部合同 - 查询所有非草稿和非协商中的合同
                    return getAllContractsOptimized(myContractQuery, request);
                case 1: // 我的合同 - 我申请的
                    myContractQuery.setContractType(MyContractQueryDTO.MyContractType.APPLIED);
                    Page<ContractDTO> myContractsResult = getMyContractsOptimized(myContractQuery, request.getUserId());
                    // contract/list接口不需要arrivalTime字段，但保留其他所有字段结构
                    myContractsResult.getRecords().forEach(contract -> contract.setArrivalTime(null));
                    return myContractsResult;
                case 2: // 我的草稿
                    return getMyDraftContractsOptimized(myContractQuery, request.getUserId());
                default:
                    myContractQuery.setContractType(MyContractQueryDTO.MyContractType.APPLIED);
                    Page<ContractDTO> defaultResult = getMyContractsOptimized(myContractQuery, request.getUserId());
                    // 移除arrivalTime字段
                    defaultResult.getRecords().forEach(contract -> contract.setArrivalTime(null));
                    return defaultResult;
            }
        }
        
        // 默认查询我申请的合同
        myContractQuery.setContractType(MyContractQueryDTO.MyContractType.APPLIED);
        Page<ContractDTO> defaultResult = getMyContractsOptimized(myContractQuery, request.getUserId());
        // 移除arrivalTime字段
        defaultResult.getRecords().forEach(contract -> contract.setArrivalTime(null));
        return defaultResult;
    }
    
    /**
     * 查询全部合同（不包括草稿和协商中）- 使用高性能模糊搜索
     */
    private Page<ContractDTO> getAllContractsOptimized(MyContractQueryDTO dto, ContractListReqDTO originalRequest) {
        try {
            // 获取租户权限
            List<String> tenantKeys = getTenantKeysWithIsolation();
            
            // 定义要查询的合同状态（排除草稿和协商中）
            List<String> statusList = Arrays.asList(
                "IN_APPROVAL", "EFFECTIVE", "TERMINATED", "EXPIRED", "REJECTED","APPROVED","ARCHIVED","SEALED"
            );
            
            // 使用新的高性能模糊搜索方法
            List<Map<String, Object>> allContractMaps = contractMapper.selectContractsWithFuzzySearch(
                tenantKeys, 
                statusList, 
                dto.getKeyword(), 
                null // 不限制申请人，查询全部合同
            );
            
            if (allContractMaps.isEmpty()) {
                Page<ContractDTO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
                page.setTotal(0);
                page.setRecords(Collections.emptyList());
                return page;
            }
            
            // 批量构建 ContractDTO
            List<ContractDTO> contracts = buildContractDTOsBatch(allContractMaps);
            
            // 应用动态字段过滤
            contracts = applyDynamicFieldFilters(contracts, originalRequest);
            
            // 去重和排序
            contracts = deduplicateContractsByContractId(contracts);
            contracts.sort((c1, c2) -> {
                LocalDateTime time1 = c1.getUpdatedAt() != null ? c1.getUpdatedAt() : c1.getCreatedAt();
                LocalDateTime time2 = c2.getUpdatedAt() != null ? c2.getUpdatedAt() : c2.getCreatedAt();
                if (time1 == null && time2 == null) return 0;
                if (time1 == null) return 1;
                if (time2 == null) return -1;
                return time2.compareTo(time1);
            });
            
            // 手动分页
            int total = contracts.size();
            int fromIndex = (dto.getPageIndex() - 1) * dto.getPageSize();
            int toIndex = Math.min(fromIndex + dto.getPageSize(), total);
            
            List<ContractDTO> pagedContracts = Collections.emptyList();
            if (fromIndex < total) {
                pagedContracts = contracts.subList(fromIndex, toIndex);
            }
            
            // 移除arrivalTime字段
            pagedContracts.forEach(contract -> contract.setArrivalTime(null));
            
            Page<ContractDTO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
            page.setTotal(total);
            page.setRecords(pagedContracts);
            
            log.info("✅ 全部合同查询完成，返回 {} 条记录，总计 {} 条", pagedContracts.size(), total);
            return page;
            
        } catch (Exception e) {
            log.error("查询全部合同失败", e);
            Page<ContractDTO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
            page.setTotal(0);
            page.setRecords(Collections.emptyList());
            return page;
        }
    }
    
    /**
     * 查询我的草稿合同 - 直接使用现有的my-contracts逻辑
     */
    private Page<ContractDTO> getMyDraftContractsOptimized(MyContractQueryDTO dto, Long userId) {
        try {
            // 对于草稿，可以直接使用原始的合同查询逻辑，因为草稿状态在合同表中
            // 设置查询类型为草稿并复用现有查询
            LambdaQueryWrapper<ContractEntity> queryWrapper = new LambdaQueryWrapper<>();
            
            // 租户权限 - 使用与协商列表接口相同的租户隔离逻辑
            List<String> tenantKeys = getTenantKeysWithIsolation();
            if (tenantKeys != null && !tenantKeys.isEmpty()) {
                queryWrapper.in(ContractEntity::getSysTenantKey, tenantKeys);
            }
            
            // 草稿状态
            queryWrapper.eq(ContractEntity::getCurrentStatus, "DRAFT");
            
            // 过滤is_matched字段
            queryWrapper.and(wrapper -> wrapper.isNull(ContractEntity::getIsMatched)
                    .or().ne(ContractEntity::getIsMatched, 1));
            
            // 申请人过滤
            if (userId != null) {
                String applicantSql = String.format(
                    "SELECT 1 FROM contract_field_value cfv WHERE cfv.contract_id = contract.id " +
                    "AND cfv.field_id = 2 AND cfv.field_value = '%s'", userId);
                queryWrapper.exists(applicantSql);
            }
            
            // 排序
            queryWrapper.orderByDesc(ContractEntity::getUpdatedAt);
            
            // 分页查询
            Page<ContractEntity> entityPage = new Page<>(dto.getPageIndex(), dto.getPageSize());
            Page<ContractEntity> contractPage = contractMapper.selectPage(entityPage, queryWrapper);
            
            if (contractPage.getRecords().isEmpty()) {
                Page<ContractDTO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
                page.setTotal(0);
                page.setRecords(Collections.emptyList());
                return page;
            }
            
            // 转换为Map格式，复用buildContractDTOsBatch逻辑
            List<Map<String, Object>> contractMaps = contractPage.getRecords().stream()
                .map(this::convertEntityToMap)
                .collect(Collectors.toList());
            
            // 批量构建 ContractDTO
            List<ContractDTO> contracts = buildContractDTOsBatch(contractMaps);
            
            // 应用过滤条件
            contracts = applyFilters(contracts, dto.getKeyword());
            
            // 移除arrivalTime字段
            contracts.forEach(contract -> contract.setArrivalTime(null));
            
            Page<ContractDTO> page = new Page<>(contractPage.getCurrent(), contractPage.getSize(), contractPage.getTotal());
            page.setRecords(contracts);
            
            log.info("✅ 我的草稿查询完成，返回 {} 条记录，总计 {} 条", contracts.size(), contractPage.getTotal());
            return page;
            
        } catch (Exception e) {
            log.error("查询我的草稿失败", e);
            Page<ContractDTO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
            page.setTotal(0);
            page.setRecords(Collections.emptyList());
            return page;
        }
    }
    
    /**
     * 获取租户权限列表 - 使用与协商列表接口相同的租户隔离逻辑
     * 优先使用当前租户，如果为空则使用租户列表
     */
    private List<String> getTenantKeysWithIsolation() {
        UserInfo currentUser = AuthUtil.getCurrentUser();
        String currentSysTenantKey = currentUser != null ? currentUser.getSysTenantKey() : null;
        
        if (currentSysTenantKey != null && !currentSysTenantKey.trim().isEmpty()) {
            // 如果当前用户有明确的sysTenantKey，只查询该租户下的数据
            log.debug("使用当前租户过滤合同数据，租户键: {}", currentSysTenantKey);
            return List.of(currentSysTenantKey);
        } else {
            // 如果sysTenantKey为null或空，使用原有逻辑（查询用户有权限的所有租户）
            List<String> userTenantKeys = AuthUtil.getUserTenantKeys();
            log.debug("使用租户列表过滤合同数据，租户键列表: {}", userTenantKeys);
            return userTenantKeys;
        }
    }
    
    /**
     * 灵活解析日期时间字符串，支持多种格式
     * 对于纯日期格式（如2025-08-05），转换为当天的00:00:00，JSON输出时只显示日期部分
     */
    private LocalDateTime parseFlexibleDateTime(String dateTimeStr) {
        if (StringUtils.isBlank(dateTimeStr)) {
            return null;
        }
        
        try {
            // 如果只有日期部分（如：2025-08-05），转换为当天00:00:00
            // JSON序列化时会根据@JsonFormat(pattern = "yyyy-MM-dd")只显示日期部分
            if (dateTimeStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
                return LocalDate.parse(dateTimeStr).atStartOfDay();
            }
            
            // 尝试解析完整的日期时间格式
            if (dateTimeStr.contains(" ") || dateTimeStr.contains("T")) {
                return LocalDateTime.parse(dateTimeStr.replace(" ", "T"));
            }
            
            // 如果是其他格式，尝试直接解析
            return LocalDateTime.parse(dateTimeStr);
            
        } catch (Exception e) {
            log.warn("无法解析日期时间字符串: {}", dateTimeStr, e);
            return null;
        }
    }

    /**
     * 将ContractEntity转换为Map格式，以便复用buildContractDTOsBatch
     */
    private Map<String, Object> convertEntityToMap(ContractEntity entity) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", entity.getId());
        map.put("process_id", entity.getProcessId());
        map.put("approval_instance_id", entity.getApprovalInstanceId());
        map.put("approval_process_id", entity.getApprovalProcessId());
        map.put("current_status", entity.getCurrentStatus());
        map.put("content", entity.getContent());
        map.put("main_contract_file_id", entity.getMainContractFileId());
        map.put("sys_tenant_key", entity.getSysTenantKey());
        map.put("created_at", entity.getCreatedAt());
        map.put("updated_at", entity.getUpdatedAt());
        map.put("arrival_time", null); // 草稿没有到达时间
        // 注意：contract_type_id 等字段通过 contract_field_value 表存储，会在 buildContractDTOsBatch 中查询
        return map;
    }
    
    /**
     * 应用动态字段过滤条件
     */
    private List<ContractDTO> applyDynamicFieldFilters(List<ContractDTO> contracts, ContractListReqDTO request) {
        if (request.getDynamicFieldConditions() == null || request.getDynamicFieldConditions().isEmpty()) {
            return contracts;
        }
        
        return contracts.stream().filter(contract -> {
            return matchesDynamicFieldConditions(contract, request.getDynamicFieldConditions());
        }).collect(Collectors.toList());
    }
    
    /**
     * 检查合同是否匹配动态字段条件
     */
    private boolean matchesDynamicFieldConditions(ContractDTO contract, List<ContractListReqDTO.DynamicFieldSearchCondition> conditions) {
        if (conditions == null || conditions.isEmpty()) {
            return true;
        }
        
        Map<Long, String> fieldValueMap = new HashMap<>();
        if (contract.getFields() != null) {
            for (ContractDTO.ModuleDTO.FieldDTO field : contract.getFields()) {
                fieldValueMap.put(field.getId(), field.getFieldValue());
            }
        }
        
        for (ContractListReqDTO.DynamicFieldSearchCondition condition : conditions) {
            String fieldValue = fieldValueMap.get(condition.getFieldId());
            if (!matchesFieldCondition(fieldValue, condition)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 检查字段值是否匹配条件
     */
    private boolean matchesFieldCondition(String fieldValue, ContractListReqDTO.DynamicFieldSearchCondition condition) {
        if (fieldValue == null && condition.getValue() != null) {
            return false;
        }
        
        String fieldType = condition.getFieldType();
        Object conditionValue = condition.getValue();
        
        switch (fieldType) {
            case "SINGLE_TEXT":
                // 模糊匹配
                return fieldValue != null && fieldValue.contains(String.valueOf(conditionValue));
                
            case "PERSON":
                // 用户ID精确匹配，绑定sys_user表的id
                return Objects.equals(fieldValue, String.valueOf(conditionValue));
                
            case "DATE":
                // 时间范围匹配，传入的是时间数组[startDate, endDate]
                return matchesDateRange(fieldValue, conditionValue);
                
            case "NUMBER":
                // 数字范围匹配，传入的是数字数组[minValue, maxValue]
                return matchesNumberRange(fieldValue, conditionValue);
                
            case "MULTI_TEXT":
                // 多行文本模糊匹配
                return fieldValue != null && fieldValue.contains(String.valueOf(conditionValue));
                
            case "DEPARTMENT":
                // 存储的是sys_department表的id，精确匹配
                return Objects.equals(fieldValue, String.valueOf(conditionValue));
                
            case "SINGLE_SELECT":
            case "MULTI_SELECT":
            case "DROPDOWN_MULTI":
            case "DROPDOWN_SINGLE":
            case "TREE_SINGLE":
            case "TREE_MULTI":
                // 存储的是code，精确匹配
                return matchesCodeValue(fieldValue, conditionValue);
                
            case "CONTRACT_TYPE":
                // 存储的是contract_type表的id，精确匹配
                return Objects.equals(fieldValue, String.valueOf(conditionValue));
                
            case "COUNTERPART_SELF":
            case "COUNTERPART_PEER":
                // 存储的是legal_entity_detail和counterparty_info的id数组，格式为[1]或者[1,2]
                return matchesIdArray(fieldValue, conditionValue);
                
            default:
                return Objects.equals(fieldValue, String.valueOf(conditionValue));
        }
    }
    
    /**
     * 匹配时间范围
     */
    private boolean matchesDateRange(String fieldValue, Object conditionValue) {
        if (fieldValue == null || conditionValue == null) {
            return false;
        }
        
        try {
            // 解析字段值为日期
            LocalDateTime fieldDate = parseFlexibleDateTime(fieldValue);
            if (fieldDate == null) {
                return false;
            }
            
            // 解析条件值为日期数组
            List<?> dateArray = (List<?>) conditionValue;
            if (dateArray.size() != 2) {
                return false;
            }
            
            LocalDateTime startDate = parseFlexibleDateTime(String.valueOf(dateArray.get(0)));
            LocalDateTime endDate = parseFlexibleDateTime(String.valueOf(dateArray.get(1)));
            
            if (startDate == null || endDate == null) {
                return false;
            }
            
            // 检查字段日期是否在范围内
            return !fieldDate.isBefore(startDate) && !fieldDate.isAfter(endDate);
            
        } catch (Exception e) {
            log.error("匹配时间范围失败", e);
            return false;
        }
    }
    
    /**
     * 匹配数字范围
     */
    private boolean matchesNumberRange(String fieldValue, Object conditionValue) {
        if (fieldValue == null || conditionValue == null) {
            return false;
        }
        
        try {
            // 解析字段值为数字
            Double fieldNumber = Double.parseDouble(fieldValue);
            
            // 解析条件值为数字数组
            List<?> numberArray = (List<?>) conditionValue;
            if (numberArray.size() != 2) {
                return false;
            }
            
            Double minValue = Double.parseDouble(String.valueOf(numberArray.get(0)));
            Double maxValue = Double.parseDouble(String.valueOf(numberArray.get(1)));
            
            // 检查字段数字是否在范围内
            return fieldNumber >= minValue && fieldNumber <= maxValue;
            
        } catch (Exception e) {
            log.error("匹配数字范围失败", e);
            return false;
        }
    }
    
    /**
     * 匹配代码值（支持多选字段的JSON数组格式）
     */
    private boolean matchesCodeValue(String fieldValue, Object conditionValue) {
        if (fieldValue == null || conditionValue == null) {
            return false;
        }
        
        String targetCode = String.valueOf(conditionValue);
        
        // 如果字段值是JSON数组格式，解析后匹配
        if (fieldValue.startsWith("[") && fieldValue.endsWith("]")) {
            try {
                List<String> codes = JSON.parseArray(fieldValue, String.class);
                return codes.contains(targetCode);
            } catch (Exception e) {
                log.error("解析代码数组失败: {}", fieldValue, e);
                return false;
            }
        }
        
        // 单个值直接匹配
        return Objects.equals(fieldValue, targetCode);
    }
    
    /**
     * 匹配ID数组（COUNTERPART_SELF和COUNTERPART_PEER字段）
     */
    private boolean matchesIdArray(String fieldValue, Object conditionValue) {
        if (fieldValue == null || conditionValue == null) {
            return false;
        }
        
        try {
            // 解析字段值为ID数组
            List<Integer> fieldIds = parseIdsFromJson(fieldValue);
            if (fieldIds.isEmpty()) {
                return false;
            }
            
            // 条件值可能是单个ID或ID数组
            List<Integer> targetIds = new ArrayList<>();
            if (conditionValue instanceof List) {
                List<?> conditionList = (List<?>) conditionValue;
                for (Object item : conditionList) {
                    targetIds.add(Integer.parseInt(String.valueOf(item)));
                }
            } else {
                targetIds.add(Integer.parseInt(String.valueOf(conditionValue)));
            }
            
            // 检查是否有交集
            return fieldIds.stream().anyMatch(targetIds::contains);
            
        } catch (Exception e) {
             log.error("匹配ID数组失败: fieldValue={}, conditionValue={}", fieldValue, conditionValue, e);
             return false;
         }
     }
     

 
 }